package org.ia2;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.UnreadableException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class RoteadorAgent extends Agent {
    List<Host> DHCPTable = new ArrayList<Host>();
    protected void setup (){
        // DHCP Behaviour
        addBehaviour (new CyclicBehaviour(this){
            public void action() {
//                final MessageTemplate msgTemplate = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
                final ACLMessage msg = this.myAgent.receive(/*msgTemplate*/);
                //2) check its caracts
                if (msg != null && msg.getOntology().equals("DHCP_REQUEST")) {
                    System.out.println(this.myAgent.getLocalName()+": Recebida solicitação DHCP de "+msg.getSender().getLocalName());

                    //3) answer
                    final ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
                    msg2.setSender(this.myAgent.getAID());
                    msg2.addReceiver(new AID(msg.getSender().getLocalName(), AID.ISLOCALNAME));
                    msg2.setOntology("DHCP_RESPONSE");
                    String addrToSet = avaibleAddress();
                    msg2.setContent(addrToSet);
                    DHCPTable.add(
                            new Host(addrToSet,
                                    (new AID(msg.getSender().getLocalName(), AID.ISLOCALNAME)),
                                    (new AID(msg.getSender().getLocalName(), AID.ISLOCALNAME).getLocalName())));
                    this.myAgent.send(msg2);

                }else if (msg != null && msg.getOntology().contains("NET_PACKET_")) {
                    try {
//                        System.out.println(this.myAgent.getLocalName()+": Recebi de: "+msg.getSender().getLocalName()+" = "+msg.getContentObject().toString());
                        Pacote pkt = (Pacote)msg.getContentObject();

                        //3) route
                        final ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
                        msg2.setSender(this.myAgent.getAID());
                        msg2.addReceiver(getAgentFromDHCPTable(pkt.getDestIPAddress()));
                        msg2.setOntology(msg.getOntology());
                        msg2.setContentObject(msg.getContentObject());
                        if(getAgentFromDHCPTable(pkt.getDestIPAddress()) != null) {
                            System.out.println(this.myAgent.getLocalName() + ": Roteando "+ msg.getOntology() + " de " + pkt.getSrcIPAddress() +" para " + pkt.getDestIPAddress());
                            this.myAgent.send(msg2);
                        }else{
                            System.out.println("Erro ao determinar o destino do pacote: Host inexistente.");
                            block();
                        }
                    } catch (UnreadableException | IOException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    block();
                }
            }
        });
    }


    private String avaibleAddress() {
        if(DHCPTable.isEmpty()){
            return "192.168.1.2";
        }
        String lastIP = DHCPTable.get(DHCPTable.size() - 1).getIPAddress();
        int lastOctet = Integer.parseInt(lastIP.split("\\.")[3]);
        if(lastOctet < 254) {
            return "192.168.1." + (lastOctet + 1);
        }else{
            return null;
        }
    }

    private AID getAgentFromDHCPTable(String IP) {
        for (Host host : DHCPTable) {
            if (host.getIPAddress().equals(IP)) {
                return host.getMACAddress();
            }
        }
        return null;
    }
}